home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_200 / 259_01 / prfrpt.c < prev    next >
Encoding:
C/C++ Source or Header  |  1988-02-23  |  15.9 KB  |  482 lines

  1.  
  2. /***************************************************************************/
  3. /* PRFRPT - Utility to generate a profile report showing the areas where   */
  4. /*          an application program is spending its time.                   */
  5. /*                                                                         */
  6. /*                                                                         */
  7. /***************************************************************************/
  8. /*                           Modification Log                              */
  9. /***************************************************************************/
  10. /* Version   Date   Programmer   -----------  Description  --------------- */
  11. /*                                                                         */
  12. /* V01.00   010788  Bob Withers  Program intially complete.                */
  13. /*                                                                         */
  14. /*                                                                         */
  15. /***************************************************************************/
  16.  
  17. #include <stdio.h>
  18. #include <stdlib.h>
  19. #include <string.h>
  20. #ifdef __TURBOC__
  21. #include <alloc.h>
  22. #else
  23. #include <malloc.h>
  24. #endif
  25. #include "profile.h"
  26.  
  27. #ifndef TRUE
  28. #define TRUE                    1
  29. #define FALSE                   0
  30. #endif
  31.  
  32. #ifndef min
  33. #define min(a, b)               ((a) < (b) ? (a) : (b))
  34. #endif
  35.  
  36. #ifdef __TURBOC__
  37. #define _fmalloc(size)          farmalloc((ulong) size)
  38. #define _ffree(ptr)             farfree(ptr)
  39. #endif
  40.  
  41. #define STATIC                  static
  42.  
  43. #define NO_ERRORS               0
  44. #define ERROR_READING_PRF       1
  45. #define ERROR_READING_PR1       2
  46. #define INVALID_PRF_FILE        3
  47. #define OUT_OF_MEMORY           4
  48.  
  49. struct sSegInfo
  50. {
  51.     ushort          uNoPubs;
  52.     ushort          uNoLins;
  53.     LPFILEPUB       lpPubEntry;
  54.     LPFILELIN       lpLinEntry;
  55.     ulong           lSegHitCnt;
  56.     FILESEG         SegRec;
  57. };
  58. typedef struct sSegInfo       SEGINFO, far *LPSEGINFO;
  59.  
  60. struct sPubRptLine
  61. {
  62.     char            cFill01[2];
  63.     char            cPubName[15];
  64.     char            cPubCnt[8];
  65.     char            cFill02[2];
  66.     char            cTotPer[4];
  67.     char            cFill03[2];
  68.     char            cHitPer[4];
  69.     char            cFill04[2];
  70.     char            cHisto[40];
  71.     char            cEos;
  72. };
  73. typedef struct sPubRptLine      PUBRPTLINE;
  74.  
  75. struct sLinRptLine
  76. {
  77.     char            cFill01[7];
  78.     char            cLineNo[5];
  79.     char            cFill02[5];
  80.     char            cLinCnt[8];
  81.     char            cFill03[2];
  82.     char            cTotPer[4];
  83.     char            cFill04[2];
  84.     char            cHitPer[4];
  85.     char            cFill05[2];
  86.     char            cHisto[40];
  87.     char            cEos;
  88. };
  89. typedef struct sLinRptLine      LINRPTLINE;
  90.  
  91.  
  92. STATIC short   near pascal BuildTables(FILE *);
  93. STATIC short   near pascal WriteReport(FILE *);
  94. STATIC void    near pascal PrintPubLine(PRPTREC, LPFILEPUB);
  95. STATIC void    near pascal PrintLinLine(PRPTREC, LPFILELIN);
  96. STATIC void    near pascal PrintLine(char *);
  97. STATIC bool    near pascal ReadPrfRec(FILE *, PFILEREC);
  98. STATIC void    near pascal ErrorMsg(char *);
  99. STATIC void    near pascal CopyStr(char far *, char far *, ushort);
  100.  
  101. static ushort              uTotSegs = 0;
  102. static ulong               lDosCnt  = 0L;
  103. static ulong               lBiosCnt = 0L;
  104. static ulong               lOthCnt  = 0L;
  105. static ulong               lHitCnt  = 0L;
  106. static ulong               lTotCnt  = 0L;
  107. static LPSEGINFO           lpSegTab = NULL;
  108. static LPFILEPUB           lpPubTab = NULL;
  109. static LPFILELIN           lpLinTab = NULL;
  110. static LPFILEMOD           lpModTab = NULL;
  111. static char                cRevision[] = "$Revision:   1.1  $";
  112. static char                cPrfFileName[MAX_PATHNAME];
  113. static char                cWrk[80];
  114. static char                cNameWrk[MAX_SEGNAME_LEN];
  115. static char               *cErrorMsgTab[] =
  116.                             {
  117.                                "",
  118.                                "Error encountered reading the .PRF file",
  119.                                "Error encountered reading the .PR1 file",
  120.                                "Invalid .PRF file encountered",
  121.                                "Out of memory while building tables"
  122.                             };
  123.  
  124.  
  125. int main(argc, argv)
  126. int       argc;
  127. char    **argv;
  128. {
  129.     auto     char       *pRev;
  130.     auto     short       nStatus;
  131.     auto     FILE       *PrfFile, *Pr1File;
  132.  
  133.     for (pRev = cRevision; *pRev; ++pRev)
  134.     {
  135.         if ('$' == *pRev)
  136.             *pRev = SPACE;
  137.     }
  138.     sprintf(cWrk, "Profile Reporting Module %s", cRevision);
  139.     ErrorMsg(cWrk);
  140.     ErrorMsg("Public Domain Software by Bob Withers, 1988");
  141.     if (argc < 2)
  142.     {
  143.         ErrorMsg("\nError - command usage is:");
  144.         ErrorMsg("        PRFRPT prffile");
  145.         ErrorMsg("           ^      ^");
  146.         ErrorMsg("           |      |");
  147.         ErrorMsg("           |      +---- Name of .PRF file from MAKEPRF");
  148.         ErrorMsg("           +------------ Utility program name");
  149.         return(1);
  150.     }
  151.     if (strchr(strcpy(strupr(cPrfFileName), argv[1]), '.') == NULL)
  152.         strcat(cPrfFileName, ".PRF");
  153.     PrfFile = fopen(cPrfFileName, "rb");
  154.     if (NULL == PrfFile)
  155.     {
  156.         sprintf(cWrk, "\nUnable to open file %s\n", cPrfFileName);
  157.         ErrorMsg(cWrk);
  158.         return(2);
  159.     }
  160.  
  161.     strcpy(strchr(cPrfFileName, '.'), ".PR1");
  162.     Pr1File = fopen(cPrfFileName, "rb");
  163.     if (NULL == Pr1File)
  164.     {
  165.         fclose(PrfFile);
  166.         sprintf(cWrk, "\nUnable to open file %s\n", cPrfFileName);
  167.         ErrorMsg(cWrk);
  168.         return(3);
  169.     }
  170.  
  171.     nStatus = BuildTables(PrfFile);
  172.     if (NO_ERRORS == nStatus)
  173.         nStatus = WriteReport(Pr1File);
  174.     if (NO_ERRORS != nStatus)
  175.         ErrorMsg(cErrorMsgTab[nStatus]);
  176.     fclose(PrfFile);
  177.     fclose(Pr1File);
  178.     return(0);
  179. }
  180.  
  181.  
  182. STATIC short near pascal BuildTables(PrfFile)
  183. FILE        *PrfFile;
  184. {
  185.     register short          i;
  186.     auto     ushort         uNoSegs = 0, uNoMods = 0;
  187.     auto     ushort         uNoPubs, uNoLins;
  188.     auto     FILEREC        PrfRec;
  189.  
  190.     if (!ReadPrfRec(PrfFile, &PrfRec))
  191.         return(ERROR_READING_PRF);
  192.     if (PRF_ID_REC == REC_TYPE && PRF_FILE_VER == FILE_VER)
  193.     {
  194.         if (memcmp(FILE_ID, PRF_FILE_ID, sizeof(FILE_ID)) != 0)
  195.             return(INVALID_PRF_FILE);
  196.     }
  197.     else
  198.         return(INVALID_PRF_FILE);
  199.  
  200.     if (!ReadPrfRec(PrfFile, &PrfRec))
  201.         return(ERROR_READING_PRF);
  202.     if (PRF_HDR_REC != REC_TYPE)
  203.         return(INVALID_PRF_FILE);
  204.     uTotSegs = NO_SEGS;
  205.     uNoPubs  = NO_PUBS;
  206.     uNoLins  = NO_LINS;
  207.     lpSegTab = (LPSEGINFO) _fmalloc(uTotSegs * sizeof(SEGINFO));
  208.     if ((LPSEGINFO) NULL == lpSegTab)
  209.         return(OUT_OF_MEMORY);
  210.     lpLinTab = (LPFILELIN) _fmalloc(uNoLins * sizeof(FILELIN));
  211.     if ((LPFILELIN) NULL == lpLinTab)
  212.     {
  213.         _ffree(lpSegTab);
  214.         return(OUT_OF_MEMORY);
  215.     }
  216.     lpPubTab = (LPFILEPUB) _fmalloc(uNoPubs * sizeof(FILEPUB));
  217.     if ((LPFILEPUB) NULL == lpPubTab)
  218.     {
  219.         _ffree(lpSegTab);
  220.         _ffree(lpLinTab);
  221.         return(OUT_OF_MEMORY);
  222.     }
  223.     lpModTab = (LPFILEMOD) _fmalloc(NO_MODS * sizeof(FILEMOD));
  224.     if ((LPFILEMOD) NULL == lpModTab)
  225.     {
  226.         _ffree(lpSegTab);
  227.         _ffree(lpLinTab);
  228.         _ffree(lpPubTab);
  229.         return(OUT_OF_MEMORY);
  230.     }
  231.     while (PRF_EOF_REC != REC_TYPE)
  232.     {
  233.         if (!ReadPrfRec(PrfFile, &PrfRec))
  234.             return(ERROR_READING_PRF);
  235.         switch (REC_TYPE)
  236.         {
  237.             case PRF_SEG_REC:
  238.                 lpSegTab[uNoSegs].uNoPubs    = 0;
  239.                 lpSegTab[uNoSegs].uNoLins    = 0;
  240.                 lpSegTab[uNoSegs].lpPubEntry = NULL;
  241.                 lpSegTab[uNoSegs].lpLinEntry = NULL;
  242.                 lpSegTab[uNoSegs].lSegHitCnt = 0L;
  243.                 lpSegTab[uNoSegs].SegRec     = PrfRec.Rec.Seg;
  244.                 ++uNoSegs;
  245.                 break;
  246.             case PRF_PUB_REC:
  247.                 for (i = 0; i < uTotSegs; ++i)
  248.                 {
  249.                     if (PUB_SEG == lpSegTab[i].SegRec.uSegVal)
  250.                     {
  251.                         lpPubTab[--uNoPubs]    = PrfRec.Rec.Pub;
  252.                         lpSegTab[i].lpPubEntry = &lpPubTab[uNoPubs];
  253.                         ++lpSegTab[i].uNoPubs;
  254.                         break;
  255.                     }
  256.                 }
  257.                 break;
  258.             case PRF_LIN_REC:
  259.                 for (i = 0; i < uTotSegs; ++i)
  260.                 {
  261.                     if (LIN_SEG == lpSegTab[i].SegRec.uSegVal)
  262.                     {
  263.                         lpLinTab[--uNoLins]    = PrfRec.Rec.Lin;
  264.                         lpSegTab[i].lpLinEntry = &lpLinTab[uNoLins];
  265.                         ++lpSegTab[i].uNoLins;
  266.                         break;
  267.                     }
  268.                 }
  269.                 break;
  270.             case PRF_MOD_REC:
  271.                 lpModTab[uNoMods++] = PrfRec.Rec.Mod;
  272.                 break;
  273.         }
  274.     }
  275.     return(NO_ERRORS);
  276. }
  277.  
  278.  
  279. STATIC short near pascal WriteReport(Pr1File)
  280. FILE            *Pr1File;
  281. {
  282.     register short       i;
  283.     register ushort      uCurSeg  = 0xffff;
  284.     auto     LPSEGINFO   lpCurSeg = NULL;
  285.     auto     RPTREC      RptRec;
  286.  
  287.     do
  288.     {
  289.         if (fread((char *) &RptRec, sizeof(RptRec), 1, Pr1File) != 1)
  290.             return(ERROR_READING_PR1);
  291.         switch (RptRec.cRecType)
  292.         {
  293.             case RPT_SEG_REC:
  294.                 uCurSeg = RptRec.uSegOfs;
  295.                 for (i = 0; i < uTotSegs; ++i)
  296.                 {
  297.                     if (uCurSeg == lpSegTab[i].SegRec.uSegVal)
  298.                     {
  299.                         lpCurSeg = &lpSegTab[i];
  300.                         CopyStr(cNameWrk, lpSegTab[i].SegRec.cSegNames,
  301.                                 lpSegTab[i].SegRec.cSegNameLen);
  302.                         sprintf(cWrk,
  303.                                 "\nSegment: %s  Length: %u (%Xh)",
  304.                                 cNameWrk, lpSegTab[i].SegRec.uSegLen,
  305.                                 lpSegTab[i].SegRec.uSegLen);
  306.                         PrintLine(cWrk);
  307.                         PrintLine("\n   Public Symbols   Count  Tot%  Hit%\n");
  308.                         break;
  309.                     }
  310.                 }
  311.                 break;
  312.             case RPT_PUB_REC:
  313.                 for (i = 0; i < lpCurSeg->uNoPubs; ++i)
  314.                 {
  315.                     if (RptRec.uSegOfs == lpCurSeg->lpPubEntry[i].uPubOfs)
  316.                     {
  317.                         PrintPubLine(&RptRec, &lpCurSeg->lpPubEntry[i]);
  318.                         break;
  319.                     }
  320.                 }
  321.                 break;
  322.             case RPT_LIN_REC:
  323.                 for (i = 0; i < lpCurSeg->uNoLins; ++i)
  324.                 {
  325.                     if (RptRec.uSegOfs == lpCurSeg->lpLinEntry[i].uLinOfs)
  326.                     {
  327.                         PrintLinLine(&RptRec, &lpCurSeg->lpLinEntry[i]);
  328.                         break;
  329.                     }
  330.                 }
  331.                 break;
  332.             case RPT_OTH_REC:
  333.                 lOthCnt  = RptRec.lCnt;
  334.                 lTotCnt += lOthCnt;
  335.                 break;
  336.             case RPT_BIO_REC:
  337.                 lBiosCnt = RptRec.lCnt;
  338.                 lTotCnt += lBiosCnt;
  339.                 break;
  340.             case RPT_DOS_REC:
  341.                 lDosCnt  = RptRec.lCnt;
  342.                 lTotCnt += lDosCnt;
  343.                 break;
  344.             case RPT_HIT_REC:
  345.                 lHitCnt  = RptRec.lCnt;
  346.                 lTotCnt += lHitCnt;
  347.                 break;
  348.         }
  349.     } while (RPT_EOF_REC != RptRec.cRecType);
  350.     _ffree(lpSegTab);
  351.     _ffree(lpPubTab);
  352.     _ffree(lpLinTab);
  353.     _ffree(lpModTab);
  354.     sprintf(cWrk, "\n    %8lu Hits in MS-DOS", lDosCnt);
  355.     PrintLine(cWrk);
  356.     sprintf(cWrk, "    %8lu Hits in ROM BIOS", lBiosCnt);
  357.     PrintLine(cWrk);
  358.     sprintf(cWrk, "    %8lu Hits in Application Pgm", lHitCnt);
  359.     PrintLine(cWrk);
  360.     sprintf(cWrk, "    %8lu Other hits", lOthCnt);
  361.     PrintLine(cWrk);
  362.     sprintf(cWrk, "    %8lu Total hits recorded", lTotCnt);
  363.     PrintLine(cWrk);
  364.     return(NO_ERRORS);
  365. }
  366.  
  367.  
  368. STATIC void near pascal PrintPubLine(pRptRec, lpPubRec)
  369. PRPTREC       pRptRec;
  370. LPFILEPUB     lpPubRec;
  371. {
  372.     auto     short          nNumStars;
  373.     auto     double         dTotPer, dHitPer;
  374.     auto     PUBRPTLINE     PubLine;
  375.  
  376.     memset((char *) &PubLine, SPACE, sizeof(PubLine));
  377.     PubLine.cEos = '\0';
  378.     CopyStr(cNameWrk, lpPubRec->cPubName, lpPubRec->cPubNameLen);
  379.     memcpy(PubLine.cPubName, cNameWrk,
  380.            min(lpPubRec->cPubNameLen, sizeof(PubLine.cPubName)));
  381.     sprintf(cWrk, "%*lu", sizeof(PubLine.cPubCnt), pRptRec->lCnt);
  382.     memcpy(PubLine.cPubCnt, cWrk, sizeof(PubLine.cPubCnt));
  383.     dTotPer = (double) pRptRec->lCnt / (double) lTotCnt * 100.0;
  384.     dHitPer = (double) pRptRec->lCnt / (double) lHitCnt * 100.0;
  385.     sprintf(cWrk, "%*.1lf", sizeof(PubLine.cTotPer), dTotPer);
  386.     memcpy(PubLine.cTotPer, cWrk, sizeof(PubLine.cTotPer));
  387.     sprintf(cWrk, "%*.1lf", sizeof(PubLine.cHitPer), dHitPer);
  388.     memcpy(PubLine.cHitPer, cWrk, sizeof(PubLine.cHitPer));
  389.     nNumStars = (short) (sizeof(PubLine.cHisto) * (dHitPer / 100.0));
  390.     if (nNumStars > 0)
  391.         memset(PubLine.cHisto, '*', nNumStars);
  392.     PrintLine((char *) &PubLine);
  393.     return;
  394. }
  395.  
  396.  
  397. STATIC void near pascal PrintLinLine(pRptRec, lpLinRec)
  398. PRPTREC       pRptRec;
  399. LPFILELIN     lpLinRec;
  400. {
  401.     auto     short          nNumStars;
  402.     auto     double         dTotPer, dHitPer;
  403.     auto     LINRPTLINE     LinLine;
  404.     static   ushort         uCurMod = 0xffff;
  405.  
  406.     if (uCurMod != lpLinRec->uLinModNum)
  407.     {
  408.         uCurMod = lpLinRec->uLinModNum;
  409.         CopyStr(cNameWrk, lpModTab[uCurMod].cModName,
  410.                           lpModTab[uCurMod].cModNameLen);
  411.         sprintf(cWrk, "\n  Line number statistics for module %s\n", cNameWrk);
  412.         PrintLine(cWrk);
  413.         PrintLine("     Line Number    Count  Tot%  Hit%\n");
  414.     }
  415.     memset((char *) &LinLine, SPACE, sizeof(LinLine));
  416.     LinLine.cEos = '\0';
  417.     sprintf(cWrk, "%*u", sizeof(LinLine.cLineNo), lpLinRec->uLinNo);
  418.     memcpy(LinLine.cLineNo, cWrk, sizeof(LinLine.cLineNo));
  419.     sprintf(cWrk, "%*lu", sizeof(LinLine.cLinCnt), pRptRec->lCnt);
  420.     memcpy(LinLine.cLinCnt, cWrk, sizeof(LinLine.cLinCnt));
  421.     dTotPer = (double) pRptRec->lCnt / (double) lTotCnt * 100.0;
  422.     dHitPer = (double) pRptRec->lCnt / (double) lHitCnt * 100.0;
  423.     sprintf(cWrk, "%*.1lf", sizeof(LinLine.cTotPer), dTotPer);
  424.     memcpy(LinLine.cTotPer, cWrk, sizeof(LinLine.cTotPer));
  425.     sprintf(cWrk, "%*.1lf", sizeof(LinLine.cHitPer), dHitPer);
  426.     memcpy(LinLine.cHitPer, cWrk, sizeof(LinLine.cHitPer));
  427.     nNumStars = (short) (sizeof(LinLine.cHisto) * (dHitPer / 100.0));
  428.     if (nNumStars > 0)
  429.         memset(LinLine.cHisto, '*', nNumStars);
  430.     PrintLine((char *) &LinLine);
  431.     return;
  432. }
  433.  
  434.  
  435. STATIC void near pascal PrintLine(pLine)
  436. register char       *pLine;
  437. {
  438.     register char      *pPtr;
  439.  
  440.     for (pPtr = &pLine[strlen(pLine) - 1]; pPtr > pLine; --pPtr)
  441.     {
  442.         if (SPACE == *pPtr)
  443.             *pPtr = '\0';
  444.         else
  445.             break;
  446.     }
  447.     fprintf(stdout, "%s\n", pLine);
  448.     return;
  449. }
  450.  
  451.  
  452. STATIC bool near pascal ReadPrfRec(PrfFile, PrfRec)
  453. FILE            *PrfFile;
  454. PFILEREC         PrfRec;
  455. {
  456.     if (fread((char *) PrfRec, sizeof(FILEPFX), 1, PrfFile) != 1)
  457.         return(FALSE);
  458.     if (fread((char *) &PrfRec->Rec,
  459.               PrfRec->Pfx.uRecLen - sizeof(FILEPFX), 1, PrfFile) != 1)
  460.         return(FALSE);
  461.     return(TRUE);
  462. }
  463.  
  464.  
  465. STATIC void near pascal ErrorMsg(pStr)
  466. char        *pStr;
  467. {
  468.     fprintf(stderr, "%s\n", pStr);
  469.     return;
  470. }
  471.  
  472.  
  473. STATIC void near pascal CopyStr(lpDest, lpSors, uCnt)
  474. char             far *lpDest, far *lpSors;
  475. register ushort       uCnt;
  476. {
  477.     while (uCnt--)
  478.         *lpDest++ = *lpSors++;
  479.     *lpDest = '\0';
  480.     return;
  481. }
  482.